﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using YogaStudio.Data;
using YogaStudio.Data.Domain;
using System.Data.Entity.Migrations;
using System.Linq.Expressions;

namespace YogaStudio.Service.BLL
{
    public class ShoppingCartService : IShoppingCartService
    {
        private readonly IYogaStudioEntities _dbContext;
        private string ShoppingCartId { get; set; }
        public const string CartSessionKey = "CartId";

        public ShoppingCartService() : this(new YogaStudioEntities()) { }

        public ShoppingCartService(IYogaStudioEntities dbContext)
        {
            _dbContext = dbContext;
        }

        public void SetCartId(HttpContextBase context)
        {
            ShoppingCartId = GetCartId(context);
        }

        public void AddToCart(int productId)
        {
            var cartItem = _dbContext.ShoppingCarts.FirstOrDefault(
                c => c.ShoppingCartId == ShoppingCartId && 
                c.ProductId == productId);

            if (cartItem == null)
            {
                cartItem = new ShoppingCart
                {
                    ProductId = productId,
                    ShoppingCartId = ShoppingCartId,
                    Quantity = 1,
                    DateCreated = DateTime.Now
                };

                _dbContext.ShoppingCarts.Add(cartItem);
                _dbContext.SaveChanges();
            }
            else
            {
                var quantity = cartItem.Quantity + 1;
                cartItem.Quantity = quantity;
                _dbContext.ShoppingCarts.AddOrUpdate(cartItem);
                _dbContext.SaveChanges();
            }
        }

        public void RemoveFromCart(int id)
        {
            var cartItem = _dbContext.ShoppingCarts.Find(id);

            if (cartItem != null)
            {
                if (cartItem.Quantity > 1)
                {
                    var quantity = cartItem.Quantity - 1;
                    cartItem.Quantity = quantity;
                    _dbContext.Entry(cartItem).State = System.Data.Entity.EntityState.Modified;
                    _dbContext.SaveChanges();
                }
                else
                {
                    _dbContext.ShoppingCarts.Remove(cartItem);
                    _dbContext.SaveChanges();
                }
            }
        }

        public void EmptyCart()
        {
            var cartItems = _dbContext.ShoppingCarts.Where(cart => cart.ShoppingCartId == ShoppingCartId);

            foreach (var cartItem in cartItems)
            {
                _dbContext.ShoppingCarts.Remove(cartItem);
            }

            _dbContext.SaveChanges();
        }

        public List<ShoppingCart> GetCartItems()
        {
            return _dbContext.ShoppingCarts.Where(cart => cart.ShoppingCartId == ShoppingCartId).ToList();
        }

        public int GetCount()
        {
            int? count = (from cartItems in _dbContext.ShoppingCarts
                          where cartItems.ShoppingCartId == ShoppingCartId
                          select (int?)cartItems.Quantity).Sum();

            return count ?? 0;
        }

        public decimal GetTotal()
        {
            decimal? total = (from cartItems in _dbContext.ShoppingCarts
                              where cartItems.ShoppingCartId == ShoppingCartId
                              select (int?)cartItems.Quantity * cartItems.Product.Price).Sum();
            return total ?? decimal.Zero;
        }

        private static string GetCartId(HttpContextBase context)
        {
            Debug.Assert(context.Session != null, "context.Session != null");
            if (context.Session[CartSessionKey] == null)
            {
                if (!string.IsNullOrWhiteSpace(context.User.Identity.Name))
                {
                    context.Session[CartSessionKey] = context.User.Identity.Name;
                }
                else
                {
                    Guid tempCartId = Guid.NewGuid();
                    context.Session[CartSessionKey] = tempCartId.ToString();
                }
            }

            return context.Session[CartSessionKey].ToString();
        }

        public void MigrateCart(string userName)
        {
            var recentShoppingCartItems = _dbContext.ShoppingCarts.Where(c => c.ShoppingCartId == ShoppingCartId).ToList();
            var previousShoppingCartItems = _dbContext.ShoppingCarts.Where(x => x.ShoppingCartId == userName).ToList();

            foreach (var recentShoppingCartItem in recentShoppingCartItems)
            {
                bool matchFound = false;
                foreach (var previousShoppingCartItem in previousShoppingCartItems)
                {
                    if (recentShoppingCartItem.ProductId == previousShoppingCartItem.ProductId)
                    {
                        previousShoppingCartItem.Quantity += recentShoppingCartItem.Quantity;
                        _dbContext.ShoppingCarts.Remove(recentShoppingCartItem);
                        matchFound = true;
                        break;
                    }
                }
                if (!matchFound)
                {
                    recentShoppingCartItem.ShoppingCartId = userName;
                }
            }
            _dbContext.SaveChanges();
        }

        public void Dispose(bool disposing)
        {
            if (disposing) _dbContext.Dispose();
        }
    }
}